using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodePlex.SpaceBlock.FS;
using CodePlex.Resourceful;
using CodePlex.Resourceful.Amazon.S3;
using System.Threading;
using System.Diagnostics;

namespace CodePlex.SpaceBlock.UI.Controls.Explore
{
    public partial class GenerateSignedUrlForm : CodePlex.SpaceBlock.UI.Controls.BaseForm
    {
        private S3FileSystem _s3fs;
        private Path _selectedFile;
        private RequestStyle _currentStyle;
        private bool _formClosed;
        private TimeSpan _currentSpan;
        private bool _pending;

        public GenerateSignedUrlForm()
        {
            InitializeComponent();

            this.MinimumSize = this.Size;

            _descriptionLabel.Text = Properties.Messages.GenerateUrl_Description;

            this.InBackground(this.BackgroundLoop);

            _expireCombo.SelectedItem = "minutes";
            _typeCombo.SelectedItem = "signed";
            _styleCombo.SelectedItem = "virtual host";

            this.FormClosed += delegate
            {
                _formClosed = true;
            };


            _expireBox.TextChanged += delegate
            {
                SetUrl("");
            };



            _expireCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
            };


            _typeCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
                bool isSigned = this.IsSigned;

                _expireLabel.Visible = isSigned;
                _expireCombo.Visible = isSigned;
                _expireBox.Visible = isSigned;

            };

            _styleCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
            };


        }


        private bool IsSigned
        {
            get
            {
                return "signed".Equals(_typeCombo.SelectedItem);
            }
        }

        public void Initialize(S3FileSystem s3fs, Path selectedFile)
        {
            _s3fs = s3fs;
            _selectedFile = selectedFile;
            _lookupLink.Visible = false;
            _copyLink.Visible = false;
            this.Text = string.Format(Properties.Messages.GenerateUrl_Title, _selectedFile.Name);


            Datacenter datacenter = s3fs.GetDatacenter(selectedFile);
            ACL acl = s3fs.GetACL(selectedFile);

            bool isPublicable =
                acl.Principals.Contains(S3Constants.Principals.AllUsers)
                &&
                (
                  acl.GetPermissions(S3Constants.Principals.AllUsers).Contains(S3Constants.Permissions.Read)
                  ||
                  acl.GetPermissions(S3Constants.Principals.AllUsers).Contains(S3Constants.Permissions.FullControl)
                );
             

            bool isEU = datacenter == Datacenter.EU;


            _styleCombo.ReadOnly = isEU;
            _typeCombo.ReadOnly = !isPublicable;

            _typeCombo.SelectedItem = isPublicable ? "public" : "signed";

            if (!isPublicable)
            {
                this.Shown += delegate
                {
                    _expireBox.Focus();
                  //  _expireBox.SelectAll();
                };
            }

        }
        





        private void SetUrl(string text)
        {
            this.InDisplay(delegate
           {
               _urlBox.Text = text;

               bool showLinks = text != null && text.StartsWith("http");
               _lookupLink.Visible = showLinks;
               _copyLink.Visible = showLinks;

               if (showLinks)
               {
                   _urlBox.Focus();
                   _urlBox.SelectAll();
               }


           });
        }


        

        private void BackgroundLoop()
        {
            while (!_formClosed)
            {
  
                if (_pending && _s3fs != null && _selectedFile != null ) 
                {
                    if (_currentSpan > TimeSpan.Zero)
                    {
                        try
                        {

                       
                            bool isPublic = _currentSpan == TimeSpan.MaxValue;
                            if (isPublic)
                            {

                                string url = _s3fs.GetPublicUrl(_currentStyle, _selectedFile);

                                SetUrl(url);
                            }
                            else
                            {
                                string url = _s3fs.GetSignedUrl(_currentStyle, _selectedFile, _currentSpan);

                                SetUrl(url);

                            }
                        
                        }
                        catch (Exception ex)
                        {
                            SetUrl("Error: " + ex.Message);
                        }
                    }
                    else
                    {
                        SetUrl("");
                    }

                    _pending = false;

                }

                Thread.Sleep(500);
            }
                
        }
 
        private void _generateButton_Click(object sender, EventArgs e)
        {
            SetUrl("Generating...");

            _currentStyle = "virtual host".Equals(_styleCombo.SelectedItem) ? RequestStyle.VHost : RequestStyle.Path;

            if (this.IsSigned)
            {
                _currentSpan = TimeSpan.Zero;
                double num = default(double);
                if (double.TryParse(_expireBox.Text, out num))
                {
                    if (num > 0)
                    {
                        Dictionary<string, Converter<double, TimeSpan>> map = new Dictionary<string, Converter<double, TimeSpan>>();
                        map["seconds"] = TimeSpan.FromSeconds;
                        map["minutes"] = TimeSpan.FromMinutes;
                        map["hours"] = TimeSpan.FromHours;
                        map["days"] = TimeSpan.FromDays;

                        try
                        {
                            _currentSpan = map[_expireCombo.SelectedItem as string](num);
                        }
                        catch (Exception ex)
                        {
                            SetUrl("Error: " + ex.Message);
                            _pending = false;
                            return;
                        }
                    }
                }

                _pending = true;
            }
            else
            {
                // public
                _currentSpan = TimeSpan.MaxValue;
             
                _pending = true;
            }


           
            
        }




        private void _lookupLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                Process.Start(_urlBox.Text);
            }
            catch { }   // this will throw if FF displays a prompt on startup
        }

        private void _copyLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Clipboard.SetText(_urlBox.Text, TextDataFormat.UnicodeText);
        }
    }
}

